package com.gym.core.common;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang.StringUtils;

import com.gym.core.date.DateContants.DateFormatType;
import com.gym.core.date.DateParseUtils;

/**
 * 
 * @author wangxinchun1988@163.com
 * @date 2016-3-5 下午3:04:41
 */
public class SequenceIdGenerateUtils {
   private static final long BEGIN_DATE = DateParseUtils.convertDate("2016-01-01", DateFormatType.YYYY_MM_DD).getTime();
   private static final int localMachineAppend = Integer.parseInt(DnsUtil.getHostAddress().split("\\.")[3]);
   
   private static  AtomicInteger atomicInteger = new AtomicInteger(0);
   
   public static long generate(int businessType){
	   StringBuilder binaryStr = new StringBuilder("0");
	  
	   binaryStr.append(wrapTimeBinaryStr());
	   binaryStr.append(wrapBusinessBinaryStr(businessType));
	   
	   binaryStr.append(wrapRoomBinaryStr(1));
	   
	   binaryStr.append(wrapMachineBinaryStr(localMachineAppend)); 
	   
	   binaryStr.append(wrapSequencePeyMachine());
	   return Long.parseLong(binaryStr.toString(), 2);
   }
   
   /**
    * 39 bit */
   private static String wrapTimeBinaryStr(){
	   long currentTime = System.currentTimeMillis();
	   long timeElipse = currentTime - BEGIN_DATE;
	   return StringUtils.leftPad(Long.toBinaryString(timeElipse),39,'0');
   }
   
   /**
    * 10 bit
    */
   private static String wrapMachineBinaryStr(int machineIp){
	   return  StringUtils.leftPad(Integer.toBinaryString(machineIp), 10, '0');
   }
   
   /**
    * 5 bit
    */
   private static String wrapBusinessBinaryStr(int businessType){
	   return  StringUtils.leftPad(Integer.toBinaryString(businessType), 5, '0');
   }
   
   /**
    * 4 bit
    */
   private static String wrapRoomBinaryStr(int room){
	   return  StringUtils.leftPad(Integer.toBinaryString(room), 4, '0');
   }
   
   /**
    * 5 bit
    */
   private static String wrapSequencePeyMachine(){
	   if(atomicInteger.get() == Integer.MAX_VALUE){
		   atomicInteger = new AtomicInteger();
	   }
	   return StringUtils.leftPad(Integer.toBinaryString(atomicInteger.incrementAndGet() % 32), 5,'0');
   }
}
